package com.xnx.bincker.leader.utils;

import lombok.Data;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 获取链接信息工具
 */
@Component
@CacheConfig(cacheNames = "RestLinks")
public class RestLinkUtils {
    private final RequestMappingHandlerMapping requestMappingHandlerMapping;

    public RestLinkUtils(RequestMappingHandlerMapping requestMappingHandlerMapping) {
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
    }

    /**
     * 构建links
     */
    public static Map<String, List<Link>> links(Link... links){
        return Collections.singletonMap("links", Arrays.asList(links));
    }

    /**
     * 通过method获取Link，并自定义rel
     * @param rel 接口名称
     * @param method 接口处理方法
     */
    @Cacheable
    public Link getLink(String rel, Method method){
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()){
            if(entry.getValue().getMethod().equals(method)){
                return new Link(rel, entry.getKey());
            }
        }
        throw new RuntimeException("没有匹配任何请求的方法: method=" + method);
    }

    @Cacheable
    public Link getLink(Method method){
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()){
            if(entry.getValue().getMethod().equals(method)){
                return new Link(method.getName(), entry.getKey());
            }
        }
        throw new RuntimeException("没有匹配任何请求的方法: method=" + method);
    }

    @Data
    public static class Link implements Serializable {
        private String rel;
        private Object method;
        private Object href;

        public Link(String rel, Object method, Object href) {
            this.rel = rel;
            this.method = method;
            this.href = href;
        }

        public Link(String rel, RequestMappingInfo mappingInfo) {
            this.rel = rel;
            getLinkInfo4MappingInfo(mappingInfo);
        }

        private void getLinkInfo4MappingInfo(RequestMappingInfo mappingInfo) {
            Set<RequestMethod> methods = mappingInfo.getMethodsCondition().getMethods();
            Set<String> patterns = mappingInfo.getPatternsCondition().getPatterns();
            if(methods.size() == 1){
                method = methods.iterator().next();
            }else if(methods.size() == 0){
                method = "ALL";
            }else{
                method = methods;
            }
            if(patterns.size() == 1){
                href = patterns.iterator().next();
            }else {
                href = patterns;
            }
        }
    }
}
